#include <iostream>
#include <map>
#include <mutex>
#include <string>
using namespace std;

// 只能在堆上创建对象的类
//class HeapOnly
//{
//public:
//	static HeapOnly* CreateObj()
//	{
//		return new HeapOnly;
//	}
//private:
//	HeapOnly()
//	{}
//
//	HeapOnly(const HeapOnly&) = delete;
//};

//int main()
//{
//	/*HeapOnly hp1;
//	HeapOnly* php2 = new HeapOnly;
//	static HeapOnly hp3;*/
//
//	HeapOnly* php4 =  HeapOnly::CreateObj();
//
//	//HeapOnly hp5(*php4);
//
//	delete php4;
//
//	cout << sizeof(php4) << endl;
//	cout << sizeof(size_t) << endl;
//
//
//	return 0;
//}

//class HeapOnly
//{
//public:
//	HeapOnly()
//	{}
//
//	void Destory()
//	{
//		this->~HeapOnly();
//	}
//
//private:
//	~HeapOnly()
//	{}
//
//	HeapOnly(const HeapOnly&) = delete;
//};
//
//int main()
//{
//	//HeapOnly hp1;
//	HeapOnly* php1 = new HeapOnly;
//
//	//delete php1;
//	php1->Destory();
//
//	return 0;
//}

// 请设计一个类，只能在栈上创建对象
//class StackOnly
//{
//public:
//	static StackOnly CreateObj()
//	{
//		return StackOnly();
//	}
//
//	void Print() const
//	{
//		cout << "StackOnly::Print()" << endl;
//	}
//	//void* operator new(size_t size) = delete;
//	//void operator delete(void* p) = delete;
//
//	/*StackOnly(StackOnly&& so)
//	{}*/
//private:
//	StackOnly()
//	{}
//
//	StackOnly(const StackOnly&) = delete;
//};
//
//int main()
//{
//	//StackOnly so1 = StackOnly::CreateObj();
//	//static StackOnly so4 = StackOnly::CreateObj();
//
//	//static StackOnly so2;
//	//StackOnly* pso3 = new StackOnly;
//
//	StackOnly::CreateObj().Print();
//
//	const StackOnly& so4 = StackOnly::CreateObj();
//	so4.Print();
//
//	return 0;
//}

// 单例模式的类：全局只有一个唯一对象
// 饿汉模式：一开始(main函数之前)就创建对象
// 缺点：1、单例对象初始化时数据太多，导致启动慢
//      2、多个单例类有初始化依赖关系，饿汉模式无法控制
//class InfoSingleton
//{
//public:
//	static InfoSingleton& GetInstance()
//	{
//		return _sins;
//	}
//
//	void Insert(string name, int salary)
//	{
//		_info[name] = salary;
//	}
//
//	void Print()
//	{
//		for (auto kv : _info)
//		{
//			cout << kv.first << ":" << kv.second << endl;
//		}
//		cout << endl;
//	}
//
//private:
//	InfoSingleton()
//	{}
//
//	InfoSingleton(const InfoSingleton& info) = delete;
//	InfoSingleton& operator=(const InfoSingleton& info) = delete;
//
//
//	map<string, int> _info;
//	// ...
//
//private:
//	static InfoSingleton _sins;
//};
//
//InfoSingleton InfoSingleton::_sins;
//
//int main()
//{
//	//InfoSingleton info1;
//	//InfoSingleton info2;
//	//InfoSingleton info3;
//
//	InfoSingleton::GetInstance().Insert("张三", 10000);
//	InfoSingleton& infosl = InfoSingleton::GetInstance();
//	infosl.Insert("李四", 15000);
//	infosl.Insert("赵六", 12000);
//	infosl.Insert("王五", 8000);
//	infosl.Print();
//
//	InfoSingleton::GetInstance().Insert("张三", 13000);
//	InfoSingleton::GetInstance().Print();
//
//	//InfoSingleton copy = InfoSingleton::GetInstance();
//	//copy.Insert("孙七", 50000);
//	//copy.Print();
//
//	infosl.Print();
//
//	return 0;
//}

// RAII锁管理类
template<class Lock>
class LockGuard
{
public:
	LockGuard(Lock& lk)
		:_lk(lk)
	{
		_lk.lock();
	}

	~LockGuard()
	{
		_lk.unlock();
	}

private:
	Lock& _lk;
};

// 懒汉模式：第一次获取单例对象的时候创建对象
// 1、对象在main函数之后才会创建，不会影响启动顺序
// 2、可以主动控制创建顺序
//class InfoSingleton
//{
//public:
//	// 多个线程一起调用GetInstance，存在线程安全的风险,
//	//static InfoSingleton& GetInstance()
//	//{
//	//	// 第一次获取单例对象的时候创建对象
//	//	// 双检查加锁
//	//	if (_psins == nullptr)  // 对象new出来以后，避免每次都加锁的检查，提高性能
//	//	{
//	//		// t1  t2
//	//		_smtx.lock();
//
//	//		try
//	//		{
//	//			if (_psins == nullptr)  // 保证线程安全且只new一次
//	//			{
//	//				_psins = new InfoSingleton;
//	//			}
//	//		}
//	//		catch (...)
//	//		{
//	//			_smtx.unlock();
//	//			throw;
//	//		}
//
//	//		_smtx.unlock();
//	//	}
//
//	//	return *_psins;
//	//}
//
//	static InfoSingleton& GetInstance()
//	{
//		// 第一次获取单例对象的时候创建对象
//		// 双检查加锁
//		if (_psins == nullptr)  // 对象new出来以后，避免每次都加锁的检查，提高性能
//		{
//			// t1  t2
//			//LockGuard<mutex> lock(_smtx);
//			std::lock_guard<mutex> lock(_smtx);
//
//			if (_psins == nullptr)  // 保证线程安全且只new一次
//			{
//				_psins = new InfoSingleton;
//			}	
//		}
//
//		return *_psins;
//	}
//
//	// 一般单例对象不需要考虑释放
//	// 单例对象不用时，必须手动处理，一些资源需要保存
//	// 可以手动调用主动回收
//	// 也可以让他自己在程序结束时，自动回收
//	static void DelInstance()
//	{
//		// 保存数据到文件
//		// ...
//
//		std::lock_guard<mutex> lock(_smtx);
//		if (_psins)
//		{
//			delete _psins;
//			_psins = nullptr;
//		}
//	}
//
//	// 也可以让他自己在程序结束时，自动回收
//	class GC
//	{
//	public:
//		~GC()
//		{
//			if (_psins)
//			{
//				cout << "~GC()" << endl;
//				DelInstance();
//			}
//		}
//	};
//	
//	void Insert(string name, int salary)
//	{
//		_info[name] = salary;
//	}
//
//	void Print()
//	{
//		for (auto kv : _info)
//		{
//			cout << kv.first << ":" << kv.second << endl;
//		}
//		cout << endl;
//	}
//
//private:
//	InfoSingleton()
//	{}
//
//	InfoSingleton(const InfoSingleton& info) = delete;
//	InfoSingleton& operator=(const InfoSingleton& info) = delete;
//
//
//	map<string, int> _info;
//	// ...
//
//private:
//	static InfoSingleton* _psins;
//	static mutex _smtx;
//	static GC _gc;
//};
//
//InfoSingleton* InfoSingleton::_psins = nullptr;
//mutex InfoSingleton::_smtx;
//InfoSingleton::GC InfoSingleton::_gc;
//
//int main()
//{
//	//InfoSingleton info1;
//	//InfoSingleton info2;
//	//InfoSingleton info3;
//
//	InfoSingleton::GetInstance().Insert("张三", 10000);
//	InfoSingleton& infosl = InfoSingleton::GetInstance();
//	infosl.Insert("李四", 15000);
//	infosl.Insert("赵六", 12000);
//	infosl.Insert("王五", 8000);
//	infosl.Print();
//
//	InfoSingleton::GetInstance().Insert("张三", 13000);
//	InfoSingleton::GetInstance().Print();
//
//	//InfoSingleton copy = InfoSingleton::GetInstance();
//	//copy.Insert("孙七", 50000);
//	//copy.Print();
//
//	infosl.Print();
//
//	//InfoSingleton::DelInstance();
//
//	return 0;
//}

//1、是懒汉。 因为静态的局部变量是在main函数之后才创建初始化的
//2、C++11之前，这里是不能保证sinst的初始化是线程安全的。
//3、C++11之后，可以。
class InfoSingleton
{
public:
	static InfoSingleton& GetInstance()
	{
		static InfoSingleton sinst;
		return sinst;
	}

	void Insert(string name, int salary)
	{
		_info[name] = salary;
	}

	void Print()
	{
		for (auto kv : _info)
		{
			cout << kv.first << ":" << kv.second << endl;
		}
		cout << endl;
	}

private:
	InfoSingleton()
	{
		cout << "InfoSingleton()" << endl;
	}

	InfoSingleton(const InfoSingleton& info) = delete;
	InfoSingleton& operator=(const InfoSingleton& info) = delete;


	map<string, int> _info;
	// ...
};

//int main()
//{
//	InfoSingleton::GetInstance().Insert("张三", 10000);
//	InfoSingleton& infosl = InfoSingleton::GetInstance();
//	infosl.Insert("李四", 15000);
//	infosl.Insert("赵六", 12000);
//	infosl.Insert("王五", 8000);
//	infosl.Print();
//
//	InfoSingleton::GetInstance().Insert("张三", 13000);
//	InfoSingleton::GetInstance().Print();
//	infosl.Print();
//
//	return 0;
//}

//int main()
//{
//	int i = 1;
//	// 隐式类型转换
//	double d = i;
//	printf("%d, %.2f\n", i, d);
//
//	int* p = &i;
//	// 显示的强制类型转换
//	int address = (int)p;
//
//	printf("%x, %d\n", p, address);
//
//	return 0;
//}

//void insert(size_t pos, char ch)
//{
//	// pos是0的时候，死循环
//	int end = _size;
//	while (end >= pos)
//	{
//		// 挪动数据
//		--end;
//	}
//
//	_str[pos] = ch;
//}
//
//int main()
//{
//	int i = 1;
//	// 隐式类型转换
//	double d = i;
//	printf("%d, %.2f\n", i, d);
//
//	int* p = &i;
//	// 显示的强制类型转换
//	int address = (int)p;
//
//	printf("%x, %d\n", p, address);
//
//	return 0;
//}

//
//int main()
//{
//	//int i = 1;
//	//// C++规范转换 -- static_cast适用相似类型的转换（这些类型的表示意义差不多）
//	//double d = static_cast<double>(i);
//	//printf("%d, %.2f\n", i, d);
//
//	//int* p = &i;
//	//// C++规范转换 --reinterpret_cast适用于不相关的类型之间的转换
//	//int address = reinterpret_cast<int>(p);
//	//printf("%x, %d\n", p, address);
//
//	// C++规范转换 -- const_cast 去掉const属性。单独分出来，警示你这个很危险，用的时候谨慎一点
//	//volatile const int a = 2;
//	//int* p = const_cast<int*>(&a);
//	//*p = 3;
//	//cout << a << endl;  // 
//	//cout << *p << endl;
//
//
//	return 0;
//}

class A
{
public:
	virtual void f(){}

	int _a = 0;
};

class B : public A
{
public:
	int _b = 0;
};

//void Func(A* ptr)
//{
//	// 直接转换是不安全的
//	B* bptr = (B*)ptr;
//	cout << bptr << endl;
//
//	bptr->_a++;
//	bptr->_b++;
//
//	cout << bptr->_a << endl;
//	cout << bptr->_b << endl;
//}

void Func(A* ptr)
{
	// C++规范的dynamic_cast是安全的
	// 如果ptr是指向父类，则转换失败，返回空
	// 如果ptr是指向子类，则转换成功
	B* bptr = dynamic_cast<B*>(ptr);
	cout << bptr << endl;

	if (bptr)
	{
		bptr->_a++;
		bptr->_b++;

		cout << bptr->_a << endl;
		cout << bptr->_b << endl;
	}
}

int main()
{
	A aa;
	B bb;
	Func(&aa);
	Func(&bb);

	return 0;
}